const asyncProcess = require('../util/asyncProcess');
const Jwt = require('../util/Jwt');

const {
    User,
    Comment,
    Like,
    Follow,
    Post,
    Op,
    Cover,
    Category
} = require('../db');
const follow = require('../db/model/follow');
const like = require('../db/model/like');

//抽离检测用户是否正确功能
const isUserError = async function (req, res, next) {
    let userData = await User.findOne({
        attributes: ['id'],
        where: {
            id: req.userId
        }
    });

    // 验证token
    if (!userData) {
        next('Token Error');
        return true;
    }
    return false;
};

// 抽离获取用户关注信息功能
const getFollowState = async function (req, res, next) {
    if (await isUserError(req, res, next)) return; //用户无效
    const {
        id: followUserId
    } = req.params;

    let followData = await Follow.findOne({
        attributes: ['has_follow'],
        where: {
            userId: req.userId,
            followUserId
        }
    });

    const {
        has_follow
    } = followData;

    return {
        has_follow,
        userId: req.userId,
        followUserId
    }
};

const processPost = async function (post) { //文章数据处理工具
    post.user.gender = +post.user.gender;
    post.comment_length = await Comment.count({
        where: {
            postId: post.id
        }
    });
    return post;
};

const userController = {
    // test(req, res) {
    //     res.send({
    //         code: 200,
    //         msg: '测试'
    //     })
    // },
    // 登录功能
    async login(req, res) {
        const {
            username,
            password
        } = req.body;

        let data = await User.findOne({
            where: {
                username
            }
        });

        if (!data) {
            return res.send({
                statusCode: 401,
                message: '用户名不存在'
            })
        }
        data = JSON.parse(JSON.stringify(data));
        if (data.password != password) {
            return res.send({
                statusCode: 401,
                message: '密码错误'
            })
        }
        const {
            gender, //处理性别
            id: userId
        } = data

        const token = Jwt(userId).createToken();

        res.send({
            message: '登录成功',
            data: {
                user: { //用户数据
                    ...data,
                    gender: +gender
                },
                token //token令牌
            }
        });
    },

    //注册功能
    async register(req, res) {
        const {
            username,
            password,
            nickname
        } = req.body;

        //查找是否存在重复用户名
        let usernameData = await User.findOne({
            where: {
                username
            }
        });
        if (usernameData) {
            res.send({
                statusCode: 400,
                message: '用户名已存在'
            })
        }

        let oldUsers = await User.findAll({
            attributes: ['id']
        });
        let posts = await Post.findAll({
            attributes: ['id']
        });

        //增加数据
        let data = await User.create({
            username,
            password,
            nickname,
            head_img: '/images/IMG1568705287936.jpeg',
            gender: 1,
            create_date: new Date().toLocaleString().replace(/([\d-]+)[^\d-:]*([\d:]+).+?/, '$1T$2.000Z')
        });
        data = JSON.parse(JSON.stringify(data));

        //关联到关注表
        let follows = JSON.parse(JSON.stringify(oldUsers)).map(v => {
            return {
                has_follow: false,
                followUserId: v.id,
                userId: data.id
            }
        });
        await Follow.bulkCreate(follows);

        //关联到喜欢表
        let likes = JSON.parse(JSON.stringify(posts)).map(v => {
            return {
                postId: v.id,
                userId: data.id,
                has_star: false,
                has_like: false
            }
        });
        await Like.bulkCreate(likes);

        res.send({
            message: '注册成功',
            data: {
                ...data,
                gender: +data.gender
            }
        });
    },

    //获取用户详情
    async getUser(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效
        const {
            id: userId
        } = req.params;
        if (userId != req.userId) {
            return next('Token Error');
        }

        let data = await User.findOne({
            where: {
                id: userId
            }
        });

        data = JSON.parse(JSON.stringify(data));

        // 评论总数
        const post_comments = await Comment.count({
            where: {
                userId
            }
        });

        //收藏总数
        const post_star = await Like.count({
            where: {
                userId,
                has_star: true
            }
        });

        res.send({
            message: '获取成功',
            data: {
                ...data,
                gender: +data.gender,
                post_comments,
                post_star
            }
        })

    },

    //更新用户信息
    async user_update(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效
        const {
            id: userId
        } = req.params;
        if (userId != req.userId) {
            return next('Token Error');
        }

        const {
            nickname,
            password,
            head_img,
            gender
        } = req.body;

        //更新数据
        let result = await User.update({
            nickname,
            password,
            head_img,
            gender
        }, {
            where: {
                id: userId
            }
        });

        //拿取数据
        let data = await User.findOne({
            where: {
                id: userId
            }
        });

        data = JSON.parse(JSON.stringify(data));

        res.send({
            message: '修改成功',
            data: {
                ...data,
                gender: +data.gender
            }
        });
    },

    //关注用户
    async user_follow(req, res, next) {
        const {
            has_follow,
            userId,
            followUserId
        } = await getFollowState(req, res, next);

        if (has_follow) { //本就已关注  `
            return res.send({
                statusCode: 401,
                message: '已关注该用户'
            })
        }
        // 修改关注状态
        let result = await Follow.update({
            has_follow: true
        }, {
            where: {
                userId,
                followUserId
            }
        });

        res.send({
            message: '关注成功'
        })
    },

    //取消用户关注
    async user_unfollow(req, res, next) {
        const {
            has_follow,
            userId,
            followUserId
        } = await getFollowState(req, res, next);

        if (!has_follow) {
            return res.send({
                statusCode: 401,
                message: '未关注该用户'
            });
        }
        // 修改关注状态
        let result = await Follow.update({
            has_follow: false
        }, {
            where: {
                userId,
                followUserId
            }
        });

        res.send({
            message: '取消关注成功'
        })
    },

    // 获取关注列表
    async getFollowList(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效

        let data = await Follow.findAll({
            where: {
                has_follow: true,
                userId: req.userId
            },
            include: {
                model: User,
                as: 'followUser',
                attributes: {
                    exclude: ['password']
                }
            }
        });
        //数据处理
        data = JSON.parse(JSON.stringify(data)).map(v => {
            const {
                followUser
            } = v;
            return {
                ...followUser,
                gender: +followUser.gender
            }
        })

        res.send({
            data
        });
    },

    // 获取用户评论列表
    async getCommentList(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效

        let data = await Comment.findAll({
            where: {
                userId: req.userId
            },
            attributes: {
                exclude: ['userId', 'postId']
            },
            include: {
                model: Post,
                attributes: ['id', 'title', 'type', 'create_date', 'content']
            },
            order: [
                ['id', 'DESC']
            ]
        });
        data = JSON.parse(JSON.stringify(data));

        //遍历评论集合
        for (let i = 0, len = data.length; i < len; i++) {
            let temp = data[i]; //每一项
            let {
                parentId //取父评论id
            } = temp;

            while (parentId) {
                let parent = await Comment.findOne({
                    where: {
                        id: parentId
                    },
                    attributes: {
                        exclude: ['userId', 'postId']
                    },
                    include: [{
                            model: Post,
                            attributes: ['id', 'title', 'type', 'create_date', 'content']
                        },
                        {
                            model: User,
                            attributes: {
                                exclude: ['password']
                            }
                        }
                    ]
                });
                parent = JSON.parse(JSON.stringify(parent));
                parentId = parent.parentId //id下移
                delete parent.parentId; //清除父评论id
                temp.parent = parent; //挂载父评论
                temp = parent; //指针下移
            }

            delete temp.parentId; //清除最外层parentId
            temp.parent = null; //最外层父评论为null
        }

        res.send({
            data
        })
    },

    //获取用户收藏文章列表
    async getStarList(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效

        //查询收藏列表
        let data = await Like.findAll({
            where: {
                userId: req.userId,
                has_star: true
            },
            include: {
                model: Post,
                attributes: {
                    exclude: ['userId']
                },
                include: [{
                    model: User,
                    attributes: {
                        exclude: ['password']
                    }
                }, {
                    model: Cover,
                    as: 'cover'
                }]
            }
        });
        //数据处理
        data = await Promise.all(JSON.parse(JSON.stringify(data)).map(async v => {
            return await processPost(v.post);
        }));

        res.send({
            data,
            message: ''
        });
    },

    //文件上传接口
    async upload(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效
        let result = await Cover.create({
            url: `/images/${req.file.filename}`
        });

        let data = await Cover.findOne({
            order: [
                ['id', 'DESC']
            ],
            attributes: {
                exclude: ['postId']
            }
        });
        data = JSON.parse(JSON.stringify(data));
        res.send({
            message: '文件上传成功',
            data: {
                ...data,
                uid: data.id
            }
        });
    },

    //收藏文章
    async post_star(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效
        const {
            id: postId
        } = req.params;
        const {
            userId
        } = req;
        //收藏数据
        let starData = await Like.findOne({
            where: {
                userId,
                postId
            },
            attributes: ['has_star']
        });

        //拿取用户id和是否收藏
        const {
            has_star
        } = starData;

        //更新收藏数据
        let result = await Like.update({
            has_star: !has_star
        }, {
            where: {
                userId,
                postId
            }
        });

        res.send({
            message: has_star ? '取消成功' : '收藏成功'
        });
    },

    //点赞文章
    async post_like(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效
        const {
            id: postId
        } = req.params;
        const {
            userId
        } = req;

        // 查询点赞数据
        let likeData = await Like.findOne({
            where: {
                userId,
                postId,
            },
            attributes: ['has_like']
        })

        //拿取用户id和是否点赞
        const {
            has_like
        } = likeData;

        //更新收藏数据
        let result = await Like.update({
            has_like: !has_like
        }, {
            where: {
                userId,
                postId
            }
        });

        res.send({
            message: has_like ? '取消成功' : '点赞成功'
        })
    },

    //发表评论
    async post_comment(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效
        const {
            id: postId
        } = req.params;
        const {
            userId
        } = req;
        const {
            content,
            parent_id
        } = req.body;

        if (!content) {
            return res.send({
                status,
                message: '无效评论'
            });
        }

        //新增评论
        let result = await Comment.create({
            content,
            parentId: parseInt(parent_id) || null,
            create_date: new Date().toLocaleString().replace(/([\d-]+)[^\d-:]*([\d:]+).+?/, '$1T$2.000Z'),
            userId,
            postId
        });

        res.send({
            message: '评论发表成功'
        });
    },

    //文章发表
    async publishPost(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效

        const {
            title,
            content,
            categories,
            cover,
            type
        } = req.body;

        let newPost = await Post.create({
            title,
            content,
            type,
            create_date: new Date().toLocaleString().replace(/([\d-]+)[^\d-:]*([\d:]+).+?/, '$1T$2.000Z'),
            userId: req.userId
        });

        let covers = await Cover.findAll({
            where: {
                [Op.or]: cover
            }
        });

        let category = await Category.findAll({
            where: {
                [Op.or]: categories
            }
        });

        newPost.setCover(covers); //关联到Cover
        newPost.setCategories(category); //关联到栏目
        let data = await Post.findOne({
            order: [
                ['id', 'DESC']
            ]
        });
        data = JSON.parse(JSON.stringify(data));

        let users = await User.findAll({
            attributes: ['id']
        });
        //关联到喜欢列表
        let likes = JSON.parse(JSON.stringify(users)).map(v => {
            return {
                userId: v.id,
                postId: data.id,
                has_like: false,
                has_star: false,
            }
        });
        await Like.bulkCreate(likes);

        res.send({
            message: '文章发布成功',
            data
        });

    },

    //编辑文章
    async post_update(req, res, next) {
        if (await isUserError(req, res, next)) return; //用户无效

        const {
            id: postId
        } = req.params;

        const {
            title,
            content,
            cover,
            categories,
            type
        } = req.body;

        let result = await Post.update({
            title,
            content,
            type
        }, {
            where: {
                id: postId
            }
        });

        let post = await Post.findOne({
            where: {
                id: postId
            }
        });

        //更新关联栏目表
        let categoryData = await Category.findAll({
            where: {
                [Op.or]: categories
            }
        });

        post.setCategories(categoryData);

        //更新关联封面表
        let coverData = await Cover.findAll({
            where: {
                [Op.or]: cover
            }
        });

        post.setCover(coverData);

        res.send({
            message: '文章修改成功'
        })
    }
}

asyncProcess(userController); //做一个异步处理

module.exports = userController; //暴露